package ph.com.gs3.formalistics.global.utilities.logging;

import java.io.PrintWriter;
import java.io.StringWriter;

import ph.com.gs3.formalistics.global.constants.ApplicationConfigs;
import ph.com.gs3.formalistics.global.constants.ApplicationConfigs.ApplicationMode;
import android.util.Log;

public class FLLogger {

	public static final String TAG = FLLogger.class.getSimpleName();
	private static ApplicationMode mode = ApplicationConfigs.APPLICATION_MODE;

	private static FLPersistentLogger persistentLogger;
	private static boolean traceEnabled = false;

	public static enum LogType {
		ERROR, WARNING, MESSAGE, DEBUG
	}

	public static final void log(LogType logType, String log) {
		Log.v(TAG, log);
	}

	public static final void log(String source, LogType logType, String log) {

		if (traceEnabled) {
			log = log + "\nTrace:\n" + getFormattedStackTrace();
		}

		switch (logType) {
			case ERROR:
				Log.e(source, log);
				if (persistentLogger != null) {
					persistentLogger.e(source, log);
				}
				break;
			case WARNING:
				Log.w(source, log);
				if (persistentLogger != null) {
					persistentLogger.w(source, log);
				}
				break;
			case MESSAGE:
				if (persistentLogger != null) {
					persistentLogger.d(source, log);
				} else {
					Log.v(source, log);
				}
				break;
			case DEBUG: {
				if (persistentLogger != null) {
					persistentLogger.d(source, log);
				}

				if (mode == ApplicationMode.DEVELOPMENT) {
					Log.v(source, log);
				}

				// if (persistentLogger != null && mode == MODE_PRODUCTION) {
				// persistentLogger.d(log);
				// } else {
				// Log.v(source, log);
				// }
			}

				break;
		}

	}

	// =========================================================================
	// Other utility methods

	public static final String getStringStackTrace(Throwable exception) {

		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		exception.printStackTrace(pw);
		return sw.toString();

	}

	public static String getFormattedStackTrace() {

		StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
		String row = "";
		String trace = "";

		for (StackTraceElement element : stackTraceElements) {
			if (!FLLogger.class.getName().equals(element.getClassName())
			        && element.getClassName().startsWith("ph.com.gs3.formalistics")) {
				row = "   " + element.getClassName() + "." + element.getMethodName() + " @ line "
				        + element.getLineNumber();

				trace += row + "\n";
			}

		}

		return trace + "\n";

	}

	// =========================================================================
	// Shortcut methods

	public static final void m(String source, String log) {
		log(source, LogType.MESSAGE, log);
	}

	public static final void w(String source, String log) {
		log(source, LogType.WARNING, log);
	}

	public static final void e(String source, String log) {
		log(source, LogType.ERROR, log);
	}

	public static final void d(String source, String log) {
		log(source, LogType.DEBUG, log);
	}

	// =========================================================================
	// Getters & Setters

	public static void setMode(ApplicationMode mode) {
		FLLogger.mode = mode;
	}

	public static ApplicationMode getMode() {
		return FLLogger.mode;
	}

	public static FLPersistentLogger getPersistentLogger() {
		return persistentLogger;
	}

	public static void setPersistentLogger(FLPersistentLogger persistentLogger) {
		FLLogger.persistentLogger = persistentLogger;
	}

	public static boolean isTraceEnabled() {
		return traceEnabled;
	}

	public static void setTraceEnabled(boolean traceEnabled) {
		FLLogger.traceEnabled = traceEnabled;
	}

}
